package com.log4jviewer.ui.preferences.additional;

import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

import com.log4jviewer.Activator;
import com.log4jviewer.domain.LogField;

/**
 * Class represents a part of additional preferences page. It is responsible for building a view where column
 * preferences are displayed.
 * 
 * @author <a href="mailto:rd.ryly@gmail.com">Ruslan Diachenko</a>
 */
public class ColumnPreferenceView {

    private static final Image CHECKED = Activator.getImageDescriptor(
            "icons/checkbox_checked.gif").createImage();

    private static final Image UNCHECKED = Activator.getImageDescriptor(
            "icons/checkbox_unchecked.gif").createImage();

    private Table table;

    private ColumnModelList columnModelList;

    private static TableViewer tableViewer;

    public ColumnPreferenceView(final Composite parent, final ColumnModelList columnModelList) {
        this.columnModelList = columnModelList;
        addChildControls(parent);
    }

    public static TableViewer getTableViewer() {
        return tableViewer;
    }

    // Add widgets to additional preference page.
    private void addChildControls(final Composite composite) {
        createTableViewer(composite);
        createButtons(composite);
    }

    private void createTableViewer(final Composite composite) {
        tableViewer = new TableViewer(composite, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
        tableViewer.setUseHashlookup(true);
        tableViewer.setContentProvider(new ColumnPrefsContentProvider());

        table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
        table.setLayoutData(gridData);

        createColumns();
        tableViewer.setInput(columnModelList);

        Listener paintListener = new Listener() {
            @Override
            public void handleEvent(final Event event) {
                final int isColumnDisplayId = 2;

                if ((event.index == isColumnDisplayId) && (event.type == SWT.PaintItem)) {
                    TableItem item = (TableItem) event.item;
                    Image newImage = getImage(item.getData());

                    Rectangle imageBounds = newImage.getBounds();
                    int xOffset = (tableViewer.getTable().getColumn(isColumnDisplayId)
                            .getWidth() - imageBounds.width) / 2;
                    int yOffset = (item.getBounds().height - imageBounds.height) / 2;

                    event.gc.drawImage(newImage, event.x + xOffset, event.y + yOffset);
                }
            }
        };

        tableViewer.getTable().addListener(SWT.PaintItem, paintListener);

        tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(final SelectionChangedEvent arg0) {
                tableViewer.getControl().redraw();
            }
        });
    }

    private void createColumns() {
        // Column Name
        final String columnNameTitle = "Column Name";
        final int columnNameSize = 120;
        TableViewerColumn column = createSingleColumn(tableViewer, columnNameTitle, columnNameSize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                ColumnModel columnModel = (ColumnModel) element;
                int columnIndex = columnModel.getColumnIndex();
                return LogField.values()[columnIndex].getName();
            }
        });

        // Column Width
        final String columnWidthTitle = "Column Width";
        final int columnWidthSize = 120;
        column = createSingleColumn(tableViewer, columnWidthTitle, columnWidthSize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                ColumnModel columnModel = (ColumnModel) element;
                int columnWidth = columnModel.getColumnWidth();
                return Integer.toString(columnWidth);
            }
        });
        column.setEditingSupport(new ColumnWidthCellEditor(tableViewer));

        // Display
        final String columnDisplayTitle = "Display";
        final int columnDisplaySize = 50;
        column = createSingleColumn(tableViewer, columnDisplayTitle, columnDisplaySize);
        column.setLabelProvider(new ColumnLabelProvider() {
            @Override
            public String getText(final Object element) {
                return null;
            }
        });
        column.setEditingSupport(new ColumnDisplayCellEditor(tableViewer));
    }

    private TableViewerColumn createSingleColumn(final TableViewer tableViewer, final String columnTitle,
            final int columnWidth) {
        TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NULL);
        TableColumn column = viewerColumn.getColumn();
        column.setText(columnTitle);
        column.setWidth(columnWidth);
        return viewerColumn;
    }

    private void createButtons(final Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout gridLayout = new GridLayout(1, true);
        gridLayout.marginHeight = 0;
        composite.setLayout(gridLayout);

        GridData gridData = new GridData(SWT.NONE, SWT.TOP, false, false);
        composite.setLayoutData(gridData);

        Button moveUpButton = new Button(composite, SWT.PUSH);
        moveUpButton.setText("MoveUp");
        GridData buttonGridData = new GridData(SWT.NONE);
        gridData.widthHint = 95;
        moveUpButton.setLayoutData(buttonGridData);

        moveUpButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                int pos = table.getSelectionIndex();
                if (pos >= 0) {
                    columnModelList.moveUp(pos);
                    tableViewer.refresh();
                }
            }
        });

        Button moveDownButton = new Button(composite, SWT.PUSH);
        moveDownButton.setText("MoveDown");
        moveDownButton.setLayoutData(buttonGridData);

        moveDownButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(final SelectionEvent e) {
                int pos = table.getSelectionIndex();
                if (pos >= 0) {
                    columnModelList.moveDown(pos);
                    tableViewer.refresh();
                }
            }
        });

    }

    private final Image getImage(final Object element) {
        ColumnModel columnModel = (ColumnModel) element;
        Image image = UNCHECKED;

        if (columnModel.isDisplay()) {
            image = CHECKED;
        }
        return image;
    }

    /**
     * Class provides content for Table in additional preferences (columns settings).
     */
    private class ColumnPrefsContentProvider implements IStructuredContentProvider {

        @Override
        public void dispose() {
            // no code
        }

        @Override
        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            // no code
        }

        @Override
        public Object[] getElements(final Object inputElement) {
            return columnModelList.getColumnItems();
        }
    }
}